#pragma once
//==========================================
// Interfaces.h : Defines interface classes
//==========================================

class Actor;
class ActorComponent;

typedef unsigned int ActorId;
typedef unsigned int ComponentId;

const ActorId INVALID_ACTOR_ID = 0;
const ComponentId INVALID_COMPONENT_ID = 0;

template<class T>
struct SortBySharedPtrContent
{
	bool operator()(const boost::shared_ptr<T>& lhs, const boost::shared_ptr<T>& rhs) const
	{
		return *lhs < *rhs;
	}
};


//=========================================
// class IScreenElement
// Represents each UI element like buttons
//=========================================
class IScreenElement
{
public:
	virtual HRESULT VOnRestore() = 0;
	virtual HRESULT VOnLostDevice() = 0;
	virtual HRESULT VOnRender(double time, float elapsedTime) = 0;
	virtual void VOnUpdate(int deltaMs) = 0;

	virtual int VGetZOrder() const = 0;
	virtual void VSetZOrder(int const zOrder) = 0;
	virtual bool VIsVisible() const = 0;
	virtual void VSetVisible(bool visible) = 0;

	virtual LRESULT CALLBACK VOnMsgProc(AppMsg msg) = 0;

	virtual ~IScreenElement() {}
	virtual bool const operator <(IScreenElement const &other) {return VGetZOrder() < other.VGetZOrder();}
};


//===================================================
// class IGameLogic
// Manages all the logic of the game.
// It creates, keeps, destroyes and moves the actors 
//===================================================
class IGamePhysics;

class IGameLogic
{
public:
	virtual boost::weak_ptr<Actor> VGetActor(const ActorId id) = 0;
	virtual boost::shared_ptr<Actor> VCreateActor(const std::string& actorRes, TiXmlElement* p_overrides,
		const Mat44* p_initialTransform = NULL, const ActorId serversActorId = INVALID_ACTOR_ID) = 0;
	virtual void VDestroyActor(const ActorId actorId) = 0;
	virtual bool VLoadGame(const char* p_levelResource) = 0;
	virtual void VSetProxy() = 0;
	virtual void VOnUpdate(float time, float elapsedTime) = 0;
	virtual void VChangeState(enum BaseGameState newState) = 0;
	virtual void VMoveActor(const ActorId id, const Mat44& mat) = 0;
	virtual boost::shared_ptr<IGamePhysics> VGetGamePhysics() = 0;
};


//=======================================================
// class IGameView
// This class permits to visually represent the world.
// Everything which has to be drawn is attache to a view
//=======================================================
enum GameViewType
{
	GameView_Human,		// What the human player can see
	GameView_Remote,	// The view for the remote players (multiplayer)
	GameView_AI,		// The view for the ennemies controlled by an AI
	GameView_Recorder,	// recorder view
	GameView_Other		// others...
};

typedef unsigned int GameViewId;
extern const GameViewId gc_invalidGameViewId;

class IGameView
{
public:
	virtual HRESULT VOnRestore() = 0;
	virtual void VOnRender(double time, float elapsedTime) = 0;
	virtual HRESULT VOnLostDevice() = 0;
	virtual GameViewType VGetType() = 0;
	virtual GameViewId VGetId() const = 0;
	virtual void VOnAttach(GameViewId vid, ActorId aid) = 0;

	virtual LRESULT CALLBACK VOnMsgProc(AppMsg msg) = 0;
	virtual void VOnUpdate(unsigned long deltaMs) = 0;

	virtual ~IGameView() {}
};


//=====================================================================
// These are the public APIs for any object that implements reactions
// to events sent by hardware user interface devices.
//
// TODO: IJoystickHandler and IGamepadHandler are not currently
//       implemented anywhere in the codebase. They are here
//       as examples, and could require modification to actually work!
//=====================================================================

class IKeyboardHandler
{
public:
	virtual bool VOnKeyDown(const BYTE c) = 0;
	virtual bool VOnKeyUp(const BYTE c) = 0;
};

class IPointerHandler
{
public:
	virtual bool VOnPointerMove(const Vector2& pos, const int radius) = 0;
	virtual bool VOnPointerButtonDown(const Vector2& pos, const int radius, const std::string& buttonName) = 0;
	virtual bool VOnPointerButtonUp(const Vector2& pos, const int radius, const std::string& buttonName) = 0;
};

class IJoystickHandler
{
	virtual bool VOnButtonDown(const std::string& buttonName, int const pressure) = 0;
	virtual bool VOnButtonUp(const std::string& buttonName) = 0;
	virtual bool VOnJoystick(float const x, float const y) = 0;
};

class IGamepadHandler
{
	virtual bool VOnTrigger(const std::string& triggerName, float const pressure) = 0;
	virtual bool VOnButtonDown(const std::string& buttonName, int const pressure) = 0;
	virtual bool VOnButtonUp(const std::string& buttonName) = 0;
	virtual bool VOnDirectionalPad(const std::string& direction) = 0;
	virtual bool VOnThumbstick(const std::string& stickName, float const x, float const y) = 0;
};

//================================================================
// class IResourceLoader
// The core of a resource cache system.
// It offers an interface to implement a loader for any file type.
//================================================================

class Resource;
class IResourceFile;
class ResHandle;

class IResourceLoader
{
public:
	virtual std::string VGetPattern() = 0;
	virtual bool VUseRawFile() = 0;
	virtual bool VDiscardRawBufferAfterLoad() = 0;
	virtual bool VAddNullZero() {return false;}
	virtual unsigned int VGetLoadedResourceSize(char* p_rawBuffer, unsigned int rawSize) = 0;
	virtual bool VLoadResource(char* p_rawBuffer, unsigned int rawSize, boost::shared_ptr<ResHandle> p_handle) = 0;
};

class IResourceFile
{
public:
	virtual bool VOpen() = 0;
	virtual int VGetRawResourceSize(const Resource& resource) = 0;
	virtual int VGetRawResource(const Resource& resource, char* p_buffer) = 0;
	virtual int VGetNumResources() const = 0;
	virtual std::string VGetResourceName(int num) const = 0;
	virtual bool VIsUsingDevelopmentDirectories() const = 0;
	virtual ~IResourceFile() {}
};


//=====================================================================
// enum RenderPass
// 3D scenes are drawn in passes - this enum defines the render passes
// supported by the 3D scene graph created by class Scene.
//=====================================================================

enum RenderPass
{
	RenderPass_0,
	RenderPass_Static = RenderPass_0,
	RenderPass_Actor,
	RenderPass_Sky,
	RenderPass_NotRendered,
	RenderPass_Last
};

class Scene;
class SceneNodeProperties;
class RayCast;
class LightNode;

class IRenderState
{
public:
	virtual std::string VToString() = 0;
};


//==========================================
// class IRenderer
// It abstracts the renderer implementation
// so the engine can use D3D9 or D3D11.
//==========================================

class IRenderer
{
public:
	virtual void VSetBackgroundColor(BYTE bgA, BYTE bgR, BYTE bgG, BYTE bgB) = 0; 
	virtual HRESULT VOnRestore() = 0;
	virtual void VShutdown() = 0;
	virtual bool VPreRender() = 0;
	virtual bool VPostRender() = 0;
	virtual void VCalcLighting(std::list<boost::shared_ptr<LightNode>>* p_lights, int maximumLights) = 0;
	virtual void VSetWorldTransform(const Mat44* p_mat) = 0;
	virtual void VSetViewTransform(const Mat44* p_mat) = 0;
	virtual void VSetProjectionTransform(const Mat44* p_mat) = 0;
	virtual boost::shared_ptr<IRenderState> VPrepareAlphaPass() = 0;
	virtual boost::shared_ptr<IRenderState> VPrepareSkyBoxPass() = 0;
	virtual void VDrawLine(const Vector3& from, const Vector3& to, const Color& color) = 0;
};


//=============================================================
// class ISceneNode
// This is the public interface for nodes in a 3D scene graph.
//=============================================================

class ISceneNode
{
public:
	virtual const SceneNodeProperties* const VGet() const = 0;

	virtual void VSetTransform(const Mat44* p_toWorld, const Mat44* p_fromWorld = NULL) = 0;

	virtual HRESULT VOnUpdate(Scene* p_scene, DWORD const elapsedMs) = 0;
	virtual HRESULT VOnRestore(Scene* p_scene) = 0;

	virtual HRESULT VPreRender(Scene* p_scene) = 0;
	virtual bool VIsVisible(Scene* p_scene) const = 0;
	virtual HRESULT VRender(Scene* p_scene) = 0;
	virtual HRESULT VRenderChildren(Scene* p_scene) = 0;
	virtual HRESULT VPostRender(Scene* p_scene) = 0;

	virtual bool VAddChild(boost::shared_ptr<ISceneNode> kid) = 0;
	virtual bool VRemoveChild(ActorId id) = 0;
	virtual HRESULT VOnLostDevice(Scene* p_scene) = 0;
	virtual HRESULT VPick(Scene* p_scene, RayCast* p_rayCast) = 0;


	virtual ~ISceneNode() {}
};


//=====================================================
// class IGamePhysics
// The interface definition for a generic physics API.
//=====================================================

class IGamePhysics
{
public:

	// Initialiazation and Maintenance of the Physics World
	virtual bool VInitialize() = 0;
	virtual void VSyncVisibleScene() = 0;
	virtual void VOnUpdate(float deltaSeconds) = 0; 

	// Initialization of Physics Objects
	virtual void VAddSphere(float radius, boost::weak_ptr<Actor> p_actor, /*const Mat44& initialTransform, */
		const std::string& densityStr, const std::string& physicsMaterial) = 0;
	virtual void VAddBox(const Vector3& dimensions, boost::weak_ptr<Actor> p_actor, /*const Mat44& initialTransform, */
		const std::string& densityStr, const std::string& physicsMaterial) = 0;
	virtual void VAddPointCloud(Vector3* p_verts, int numPoints, boost::weak_ptr<Actor> p_actor, 
		/*const Mat44& initialTransform, */ const std::string& densityStr, const std::string& physicsMaterial) = 0;
	virtual void VRemoveActor(ActorId id) = 0;

	// Debugging
	virtual void VRenderDiagnostics() = 0;

	// Physics world modifiers
	virtual void VCreateTrigger(boost::weak_ptr<Actor> p_actor, const Vector3& pos, const float dim) = 0;
	virtual void VApplyForce(const Vector3& dir, float newtons, ActorId aid) = 0;
	virtual void VApplyTorque(const Vector3& dir, float newtons, ActorId aid) = 0;
	virtual bool VKinematicMove(const Mat44& mat, ActorId aid) = 0;

	// Physics actor states
	virtual void VRotateY(ActorId actorId, float angleRadians, float time) = 0;
	virtual float VGetOrientationY(ActorId actorId) = 0;
	virtual void VStopActor(ActorId actorId) = 0;
	virtual Vector3 VGetVelocity(ActorId actorId) = 0;
	virtual void VSetVelocity(ActorId actorId, const Vector3& vel) = 0;
	virtual Vector3 VGetAngularVelocity(ActorId actorId) = 0;
	virtual void VSetAngularVelocity(ActorId actorId, const Vector3& vel) = 0;
	virtual void VTranslate(ActorId actorId, const Vector3& vec) = 0;

	virtual void VSetTransform(const ActorId id, const Mat44& mat) = 0;
	virtual Mat44 VGetTransform(const ActorId id) = 0;

	virtual ~IGamePhysics() {}
};


//==========================================================
// class IScriptManager
// This is the public interface for the scripting system.
//==========================================================

class IScriptManager
{
public:
	virtual ~IScriptManager() {}
	virtual bool VInit() = 0;
	virtual void VExecuteFile(const char* resource) = 0;
	virtual void VExecuteString(const char* str) = 0;
};